package com.han.controller;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.doudian.open.api.product_listV2.ProductListV2Request;
import com.doudian.open.api.product_listV2.ProductListV2Response;
import com.doudian.open.api.product_listV2.data.DataItem;
import com.doudian.open.api.product_listV2.data.ProductListV2Data;
import com.doudian.open.api.product_listV2.param.ProductListV2Param;
import com.doudian.open.api.token.AccessTokenData;
import com.doudian.open.core.AccessToken;
import com.doudian.open.core.AccessTokenBuilder;
import com.han.core.domain.RestResult;
import com.han.core.domain.dto.PullShopProductDTO;
import com.han.core.domain.entity.Product;
import com.han.core.domain.entity.ProductCategory;
import com.han.core.domain.entity.ProductSku;
import com.han.service.ProductCategoryService;
import com.han.service.ProductService;
import com.han.service.ProductSkuService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@RestController
@RequestMapping("/shop")
public class ShopController {

    private static final Logger log = LoggerFactory.getLogger(ShopController.class);
    @Resource
    ProductService productService;
    @Resource
    ProductCategoryService productCategoryService;
    @Resource
    ProductSkuService productSkuService;

    /**
     * 同步拉取商品及sku代码测试接口
     */
//    @GetMapping("/product/pull/sync")
    public RestResult<String> productPullSync(@RequestAttribute("accessToken") AccessTokenData accessTokenData) {
        //todo 先以同步的方式执行完这套插入
        LocalDateTime start = LocalDateTime.now();
        int count = 0;
        int saveCount = 0;
        AccessToken accessToken = AccessTokenBuilder.parse(accessTokenData.getAccessToken());
        final long size = 400L;
        ProductListV2Request listRequest = new ProductListV2Request();
        Snowflake snowflake = IdUtil.getSnowflake();
        int maxPage = Integer.MAX_VALUE;
        List<Object> objects = productService.listObjs(new QueryWrapper<Product>().lambda().select(Product::getProductId));
        List<Long> productIds = ConvertListClass(objects, Long.class);
        //测试商品id
        Set<Long> productIdSet = new HashSet<>(productIds);
        for (long i = 1; i <= maxPage; i++) {
            ProductListV2Param param = listRequest.getParam();
            param.setPage(i);
            param.setSize(size);
            listRequest.setParam(param);
            ProductListV2Response productListV2Response = listRequest.execute(accessToken);
            if (!"10000".equals(productListV2Response.getCode())) {
                log.warn("请求获取商品列表出现异常,msg:{}", productListV2Response.getMsg());
                throw new RuntimeException("出现异常,msg:" + productListV2Response.getMsg() + ",code:" + productListV2Response.getCode());
            }
            ProductListV2Data pageResp = productListV2Response.getData();
            if (maxPage == Integer.MAX_VALUE) {
                long total = pageResp.getTotal();
                maxPage = (int) Math.ceil((double) total / size);
            }
            List<Product> productList = new ArrayList<>((int) size);
            List<ProductCategory> productCategoryList = new ArrayList<>((int) size);
            for (DataItem x : pageResp.getData()) {
                productIdSet.add(x.getProductId());
                if (productIds.contains(x.getProductId())) {
                    //剔除数据库中已存在的数据
                    continue;
                }
                Product product = new Product();
                long productOwnId = snowflake.nextId();
                product.setShopId(Long.valueOf(accessTokenData.getShopId()));
                product.setProductOwnId(productOwnId);
                BeanUtils.copyProperties(x, product);
                productList.add(product);
                ProductCategory productCategory = new ProductCategory();
                BeanUtils.copyProperties(x.getCategoryDetail(), productCategory);
                productCategory.setProductOwnId(productOwnId);
                productCategory.setProductId(x.getProductId());
                productCategoryList.add(productCategory);
            }
            //有一个问题saveBatch后无法精确获取每个商品的id去进行关联,所以手动创建雪花算法id
            productService.saveBatch(productList);
            productCategoryService.saveBatch(productCategoryList);
            count += pageResp.getData().size();
            saveCount += productList.size();
        }
        LocalDateTime end = LocalDateTime.now();
        return RestResult.success("",
                "执行总耗时:" + Duration.between(start, end) + "/n"
                        + "本次获取总条数：" + count + "/n"
                        + "本次插入条数:" + saveCount
                        + "productIds:" + productIdSet.size()
        );
    }

    /**
     * 将任集合类型的值转换为预期的类型
     */
    public static <T> List<T> ConvertListClass(Object obj, Class<T> clazz) {
        List<T> list = new ArrayList<>();
        if (obj instanceof List) {
            for (Object o : (List<?>) obj) {
                list.add(clazz.cast(o));
            }
            return list;
        }
        return null;
    }

    /**
     * 根据所选类型拉取指定商品的子规格商品或同步店铺的所有商品
     *
     * @param dto see {@link com.han.core.domain.dto.PullShopProductDTO}
     * @return see {@link com.han.core.domain.RestResult}
     */
    @PostMapping("/product/byIds/type/pull")
    @Transactional(rollbackFor = Exception.class)
    public RestResult pullShopProductOrAll(@RequestAttribute("accessToken") AccessTokenData accessTokenData, @RequestBody PullShopProductDTO dto) {
        if (dto.getType() == 1) {
            //为同步商品，所以应先清空当前数据库中该店铺的商品
            productService.remove(new QueryWrapper<Product>().lambda().eq(Product::getShopId, accessTokenData.getShopId()));
            productSkuService.remove(new QueryWrapper<ProductSku>().lambda().eq(ProductSku::getShopId, accessTokenData.getShopId()));
            productCategoryService.remove(new QueryWrapper<ProductCategory>().lambda().eq(ProductCategory::getShopId, accessTokenData.getShopId()));
            productService.pullAllProductAsync(accessTokenData);
        }
        if (dto.getType() == 2) {
            productService.pullProductByIds(accessTokenData, dto.getProductIds());
        }
        if (dto.getType() != 1 && dto.getType() != 2) {
            return RestResult.error("type参数异常");
        }
        return RestResult.success();
    }

}
